package com.ikun.starters.jwt.impl;


import com.ikun.starters.jwt.ITokenService;
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * @author ximeng
 * @title: TokenService
 * @description: Token的实现类
 */
public class TokenService implements ITokenService {

    //过期时间
    private Integer expireTime;
    //token的签名
    private String tokenSignKey;

    private String tokenKey;

    public TokenService(Integer expireTime, String tokenSignKey, String tokenKey) {
        this.expireTime = expireTime;
        this.tokenSignKey = tokenSignKey;
        this.tokenKey = tokenKey;
    }

    @Override
    public String createToken(String userId, String username, Map<String, Object> subject) {
        return Jwts.builder()
                .setSubject(username)   //设置唯一标识
                .setId(String.valueOf(userId))  //设置id是谁
                .setExpiration(new Date(System.currentTimeMillis() + expireTime)) //过期时间
                //设置签名算法  以及签名密钥
                .signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP)
                .compact();
    }

    @Override
    public Boolean verifyToken(String token) {
        try {
            Jwts.parser().setSigningKey(tokenSignKey)
                    .parseClaimsJws(token);
            return true;
        } catch (Exception err) {
            return false;
        }
    }

    /**
     * 需要在token过期前完成token的刷新
     * @param token
     * @return
     */
    @Override
    public String refreshToken(String token) {

        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey)
                .parseClaimsJws(token);
        //下面找到用户id的信息
        String userId = claimsJws.getBody().getId();
        //这里拿到这个用户名
        String username = claimsJws.getBody().getSubject();
        //从新生成我们的数据
        return createToken(userId, username, null);
    }

    @Override
    public String getToken(HttpServletRequest req, String tokenName) {
        //这里是从头信息中去拿
        String token = req.getHeader(tokenName);
        if (StringUtils.isEmpty(token)) {
            //这里是去参数中去拿这个信息
            token = req.getParameter(this.tokenKey);
        }
        return token;
    }
}
